#include "HttpServer.h"

#include "../../base/log/Logging.h"
#include "HttpContext.h"
#include "HttpResponse.h"

namespace detail {
    /**
     * 默认的HttpCallback函数, 返回404状态码
     * @param req http请求
     * @param resp http响应
     */
    void defaultHttpCallback(const HttpRequest &req, HttpResponse *resp) {
        resp->setStatusCode(HttpResponse::k404NotFound);
        resp->setStatusMessage("Not Found");
        resp->setCloseConnection(true);
    }
}

HttpServer::HttpServer(EventLoop *loop,
                       const InetAddress &listenAddr,
                       const string &name,
                       TcpServer::Option option)
        : server_(loop, listenAddr, name, option),
          httpCallback_(detail::defaultHttpCallback)
         {
    server_.setConnectionCallback(
            std::bind(&HttpServer::onConnection,
                      this,
                      std::placeholders::_1));
    server_.setMessageCallback(
            std::bind(&HttpServer::onMessage, this, std::placeholders::_1,
                      std::placeholders::_2,
                      std::placeholders::_3));
}

void HttpServer::start() {
    LOG_TRACE << "HttpServer[" + server_.name() + "] 启动";
    server_.start();
}

void HttpServer::onConnection(const TcpConnectionPtr &conn) {
    if (conn->connected()) {
        conn->setContext(HttpContext());
        // 如果连接上就将httpContext封装进连接, 用于处理Http请求
    }
}

void HttpServer::onMessage(const TcpConnectionPtr &conn,
                           Buffer *buf,
                           Timestamp receiveTime) {
    LOG_ERROR << "请求到的缓冲区数据\n" << buf->peek();
    HttpContext * context = boost::any_cast<HttpContext>(conn->getMutableContext());
    if (!context->parseRequest(buf, receiveTime)) {
        conn->send("HTTP/1.1 400 Bad Request\r\n\r\n");
        // 用状态机去封装请求, 如果封装失败就是请求有问题, 直接返回
        conn->shutdown();
    }
    if (context->gotAll()) {
        // HttpRequest处理完毕, 调用处理http请求
        onRequest(conn, context->request());
        context->reset();
    }
}

void HttpServer::onRequest(const TcpConnectionPtr &conn, const HttpRequest &req) {
    const string &connection = req.getHeader("Connection");
    bool close = connection == "close" ||
                 (req.getVersion() == HttpRequest::kHttp10 && connection != "Keep-Alive");
    HttpResponse response(close);
    httpCallback_(req, &response);
 //   doRequest(req, &response);
   // 调用回调函数处理请求,并封装到response中
    Buffer buf;
    response.appendToBuffer(&buf);
    // 将处理结果转化为Http响应发送
    conn->send(&buf);
    if (response.closeConnection()) {
        // 如果客户端是不保持连接的话就shutdown断开写入端等待客户端关闭连接
        conn->shutdown();
    }
}



